#pragma once
#include "Endian.h"
#include "StringPiece.h"
#include <cstdint>
#include <netinet/in.h>

#include <string>
#include <sys/socket.h>

using std::string;

namespace sockets
{
const struct sockaddr* sockaddr_cast(const struct sockaddr_in6* addr);
}

class InetAddress
{
public:
    // 端口构造 loopbackonly: 是否仅绑定环回自检地址
    explicit InetAddress(uint16_t port = 0, bool loopbackOnly = false, bool ipv6 = false);
    // ip地址构造
    InetAddress(StringArg ip, uint16_t port, bool ipv6 = false);
    explicit InetAddress(const struct sockaddr_in &addr) 
    : _addr(addr) {}
    explicit InetAddress(const struct sockaddr_in6 &addr6) 
    : _addr6(addr6) {}

    // 协议族 v4 or v6
    sa_family_t family() const { return _addr.sin_family; }

    // 获取ip字符串
    string toIp() const;
    // 端口字符串
    string toIpPort() const;
    // 端口int
    uint16_t port() const;

    // 获取sockaddr指针（用于socket API）
    const struct sockaddr* getSockAddr() const
    {
        return sockets::sockaddr_cast(&_addr6);
    }

    // 设置ipv6
    void setSockAddrInet6(const struct sockaddr_in6 &addr6)
    {
        _addr6 = addr6;
    }

    // 获取IPv4地址（网络字节序）
    uint32_t ipv4NetEndian() const;

    // 获取端口号（网络字节序）
    uint16_t portNetEndian() const { return _addr.sin_port; }

    // dns解析主机名（thread safe）
    static bool resolve(StringArg hostname, InetAddress* result);

    /// 设置IPv6 Scope ID
    void setScopeId(uint32_t scope_id);

private:
    union {
        struct sockaddr_in _addr;   // ipv4 16B
        struct sockaddr_in6 _addr6; // ipv6 28B
    };

};

